use crate::entities::prelude::{CertInfo, CertRevokedList};
use crate::entities::{cert_info, cert_revoked_list};
use crate::services::cert_service;
use crate::services::cert_service::DeleteType;
use attestation_common::log::info;
use sea_orm::{
    ActiveModelTrait, ActiveValue, ColumnTrait, DatabaseConnection, DbErr, DeleteResult,
    EntityTrait, QueryFilter, QuerySelect, UpdateResult,
};

pub struct CertRepository;

impl CertRepository {
    pub async fn find_all(
        db: &DatabaseConnection,
        ids: &Option<Vec<String>>,
        cert_type: &Option<String>,
    ) -> Result<Vec<(cert_info::Model, Option<cert_revoked_list::Model>)>, DbErr> {
        info!("Fetching certs from database");

        // 构建基础查询
        let mut query = CertInfo::find();

        match ids {
            Some(ids) => {
                query
                    .filter(cert_info::Column::Id.is_in(ids.clone()))
                    .find_also_related(CertRevokedList)
                    .all(db)
                    .await
            }
            None => {
                // 如果 cert_type 不为空，添加 cert_type 过滤条件
                if let Some(cert_type) = cert_type {
                    query = query.filter(cert_info::Column::CertType.eq(cert_type.as_str()));
                }
                query
                    .select_only()
                    .column_as(cert_info::Column::Id, "id")
                    .column_as(cert_info::Column::Name, "name")
                    .column_as(cert_info::Column::Version, "version")
                    .into_model::<cert_info::SimpleInfo>()
                    .all(db)
                    .await
                    .map(|certs| {
                        certs
                            .into_iter()
                            .map(|c| {
                                (
                                    cert_info::Model {
                                        id: c.id,
                                        name: c.name,
                                        version: c.version,
                                        ..Default::default()
                                    },
                                    None,
                                )
                            })
                            .collect()
                    })
            }
        }
    }

    pub async fn find_cert_by_id(
        db: &DatabaseConnection,
        id: &String,
    ) -> Result<Option<cert_info::Model>, DbErr> {
        CertInfo::find_by_id(id.to_string()).one(db).await
    }

    pub async fn delete_certs(
        db: &DatabaseConnection,
        delete_type: DeleteType,
        ids: Option<Vec<String>>,
        cert_type: Option<String>,
    ) -> Result<DeleteResult, DbErr> {
        match delete_type {
            DeleteType::Id => {
                // 检查 ids 是否超过 10 个
                if let Some(ids) = &ids {
                    if ids.len() > cert_service::CertService::MAX_NUMBER_OF_QUERIES {
                        return Err(DbErr::Custom("IDs exceed maximum limit of 10".to_string()));
                    }
                }
                if ids.is_none() {
                    return Err(DbErr::Custom("IDs not set".to_string()));
                }

                // 删除证书信息
                let cert_delete_result = CertInfo::delete_many()
                    .filter(cert_info::Column::Id.is_in(ids.clone().unwrap_or_default()))
                    .exec(db)
                    .await?;

                // 删除证书吊销信息
                CertRevokedList::delete_many()
                    .filter(cert_revoked_list::Column::Id.is_in(ids.unwrap_or_default()))
                    .exec(db)
                    .await?;

                Ok(cert_delete_result)
            }
            DeleteType::Type => {
                // 检查 cert_type 是否合法
                let valid_types = [
                    cert_service::CertificateType::REFVALUE,
                    cert_service::CertificateType::POLICY,
                    cert_service::CertificateType::TPM_BOOT,
                    cert_service::CertificateType::TPM_IMA,
                    cert_service::CertificateType::CRL,
                ];
                if let Some(cert_type) = &cert_type {
                    if !valid_types.contains(&cert_type.as_str()) {
                        return Err(DbErr::Custom("Invalid certificate type".to_string()));
                    }
                }
                if cert_type.is_none() {
                    return Err(DbErr::Custom("certificate type not set".to_string()));
                }
                if cert_type == Some(cert_service::CertificateType::CRL.to_string()) {
                    // 删除所有证书吊销信息
                    let revoked_delete_result = CertRevokedList::delete_many().exec(db).await?;
                    Ok(revoked_delete_result)
                } else {
                    // 删除证书信息
                    let cert_delete_result = CertInfo::delete_many()
                        .filter(cert_info::Column::CertType.eq(cert_type.unwrap_or_default()))
                        .exec(db)
                        .await?;
                    Ok(cert_delete_result)
                }
            }
            DeleteType::All => {
                // 删除所有证书信息
                let cert_delete_result = CertInfo::delete_many().exec(db).await?;

                // 删除所有证书吊销信息
                CertRevokedList::delete_many().exec(db).await?;

                Ok(cert_delete_result)
            }
        }
    }

    /// 插入证书信息
    pub async fn insert_cert_info(
        db: &DatabaseConnection,
        cert_info: cert_info::ActiveModel,
    ) -> Result<(), DbErr> {
        cert_info.insert(db).await?;
        Ok(())
    }

    /// 插入证书吊销信息
    pub async fn insert_cert_revoked(
        db: &DatabaseConnection,
        cert_revoked: cert_revoked_list::ActiveModel,
    ) -> Result<(), DbErr> {
        cert_revoked.insert(db).await?;
        Ok(())
    }

    /// 更新证书信息
    pub async fn update_cert_info(
        db: &DatabaseConnection,
        id: &String,
        version: i32,
        cert_info: cert_info::ActiveModel,
    ) -> Result<UpdateResult, DbErr> {
        let update_result: UpdateResult = CertInfo::update_many()
            .set(cert_info)
            .filter(cert_info::Column::Id.eq(id.as_str()))
            .filter(cert_info::Column::Version.eq(version))
            .exec(db)
            .await?;
        Ok(update_result)
    }

    pub async fn update_cert_valid_code(
        db: &DatabaseConnection,
        id: &String,
        valid_code: Option<i32>,
    ) -> Result<cert_info::Model, DbErr> {
        let cert_info = cert_info::ActiveModel {
            id: ActiveValue::Set(id.to_string()),
            valid_code: ActiveValue::Set(valid_code),
            ..Default::default()
        };
        cert_info.update(db).await
    }

    pub async fn update_cert_revoked_valid_code(
        db: &DatabaseConnection,
        id: &String,
        valid_code: Option<i32>,
    ) -> Result<cert_revoked_list::Model, DbErr> {
        let cert_revoked = cert_revoked_list::ActiveModel {
            id: ActiveValue::Set(id.to_string()),
            valid_code: ActiveValue::Set(valid_code),
            ..Default::default()
        };
        cert_revoked.update(db).await
    }
}
